#nullable enable

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using PHMEE.CommonUtils;
using PHMEE.Localization;
using Volo.Abp.Application.Dtos;

namespace PHMEE.EnergyEfficiency;

/// <summary>
/// 开关量信号
/// </summary>
public class DigitalSignalAppService : PHMEEAppService, IDigitalSignalAppService
{
    private readonly IPHMEETimeProvider _phmeeTimeProvider;
    private readonly IDigitalTDRepository _digitalTDRepository;

    public DigitalSignalAppService(IPHMEETimeProvider phmeeTimeProvider, IDigitalTDRepository digitalTDRepository)
    {
        LocalizationResource = typeof(EnergyEfficiencyResource);

        _phmeeTimeProvider = phmeeTimeProvider;
        _digitalTDRepository = digitalTDRepository;
    }

    // 获取实时开关量信号
    public async Task<List<DigitalGroupDto>> GetRealtimeDigitalSignalsAsync(Guid vesselId)
    {
        var utcNow = _phmeeTimeProvider.GetUtcNow();

        // 查询 digital 超级表下的每一张子表中的 utcNow 之前的最新一条数据，带 Tags
        var digitalSignals =
            await _digitalTDRepository.GetLatestRecordBeforeDateTimeFromSubtablesAsync(vesselId, utcNow);

        var result = digitalSignals.GroupBy(d => d.AmsGroup).Select(g => new DigitalGroupDto
            {
                AmsGroup = g.Key,
                GroupIndex = g.First().GroupIndex,
                AlarmCount = g.Count(d => d.V == DigitalValue.Alarm),
                // 实时数据组内按照 TagName 排序
                DigitalSignals = g.OrderBy(a => a.TagName).Select(d => new DigitalSignalDto
                {
                    Ts = d.Ts,
                    TagName = d.TagName,
                    TagDesc = d.TagDesc,
                    V = d.V.ToString()
                })
            })
            .OrderBy(x => x.GroupIndex).ToList();

        return result;
    }

    // 查询报警记录
    public async Task<List<DigitalSignalDto>> GetDigitalAlarmRecordsAsync(Guid vesselId)
    {
        // 往前查一周
        var utcNow = _phmeeTimeProvider.GetUtcNow();
        var startDateTime = utcNow.AddDays(-7);
        var digitalSignals = await _digitalTDRepository.GetDigitalAlarmRecordsAsync(vesselId, startDateTime, utcNow);

        return digitalSignals.Select(d => new DigitalSignalDto
        {
            Ts = d.Ts,
            TagName = d.TagName,
            TagDesc = d.TagDesc,
            V = d.V.ToString()
        }).ToList();
    }

    /// <summary>
    /// 查询每个 tag 最新状态为报警的记录
    /// </summary>
    /// <param name="vesselId"></param>
    /// <returns></returns>
    public async Task<List<DigitalSignalDto>> GetEveryTagsLatestAlarmRecordsAsync(Guid vesselId)
    {
        var utcNow = _phmeeTimeProvider.GetUtcNow();

        // 查询 digital 超级表下的每一张子表中的 utcNow 之前的最新一条数据，带 Tags
        var digitalSignals =
            await _digitalTDRepository.GetLatestRecordBeforeDateTimeFromSubtablesAsync(vesselId, utcNow);

        var result = digitalSignals.Where(d => d.V == DigitalValue.Alarm).Select(d => new DigitalSignalDto
            {
                Ts = d.Ts,
                TagName = d.TagName,
                TagDesc = d.TagDesc,
                V = d.V.ToString()
            })
            .OrderByDescending(x => x.Ts).ToList();

        return result;
    }

    // 根据 AMS Group，查询实时的报警记录
    public async Task<List<DigitalSignalDto>> GetRealtimeDigitalAlarmRecordsByAmsGroupAsync(Guid vesselId,
        string amsGroup)
    {
        var utcNow = _phmeeTimeProvider.GetUtcNow();

        // 查询 digital 超级表下的每一张子表中的 utcNow 之前的最新一条数据，根据 ams_group 筛选
        var digitalSignals =
            await _digitalTDRepository.GetLatestRecordBeforeDateTimeByAmsGroupFromSubtablesAsync(vesselId, utcNow,
                amsGroup);

        var alarmSignals = digitalSignals.Where(d => d.V == DigitalValue.Alarm);

        return alarmSignals.Select(d => new DigitalSignalDto
        {
            Ts = d.Ts,
            TagName = d.TagName,
            TagDesc = d.TagDesc,
            V = d.V.ToString()
        }).ToList();
    }

    // 查询报警历史
    public async Task<PagedResultDto<DigitalSignalDto>> GetDigitalAlarmHistoryAsync(Guid vesselId, string? tagName,
        string? tagDescription, DateTime startDateTime, DateTime endDateTime, int skipCount, int maxResultCount)
    {
        List<string>? matchedTagdescs = null;
        if (!string.IsNullOrWhiteSpace(tagDescription))
        {
            tagDescription = tagDescription.Trim();
            
            var allDigitalTagdesc = await _digitalTDRepository.GetAllDigitalTagdescAsync(vesselId);
            var description = tagDescription;
            matchedTagdescs = allDigitalTagdesc.Where(d => d.Contains(description)).ToList();
        }

        var (totalCount, digitalSignals) = await _digitalTDRepository.GetDigitalRecordsAsync(vesselId, tagName,
            matchedTagdescs, startDateTime, endDateTime, skipCount, maxResultCount);

        var digitalSignalDtos = digitalSignals.Select(d => new DigitalSignalDto
        {
            Ts = d.Ts,
            TagName = d.TagName,
            TagDesc = d.TagDesc,
            V = d.V.ToString()
        }).ToList();

        return new PagedResultDto<DigitalSignalDto>(totalCount, digitalSignalDtos);
    }
}